GSP-005
Hello Kubernetes
2017년 10월 19일 목요일
오전 9:45
링크: https://google.qwiklabs.com/focuses/7011
참고 유튜브: https://goo.gl/3ezwCV
당신이 개발한
코드를 Kubernetes 위에 복제해서 돌려보자
그런데 Kubernetes는 Google Container Engine 위에서
돌거다
- 우리가 사용할 코드는 Hello World.js 앱이다
아래 다이어그램이
전체 조망도이다.
두고두고 살펴보자
* node = VM 한대
라고 생각하자
- 오픈소스 프로젝트이다. www.kubernetes.io
- 다양한 환경에서 동작한다
- laptop에서 multi-node clusters 까지
- public clouds에서 on-premise deployment 까지
- virtual machine 에서 bare metal (http://www.ciokorea.com/news/35402)
까지
- 매니지드 환경을 사용해서
설치 등등은 바로 넘어가는 거다
- 매니지드 환경은 Google Container Engine 을 사용할거다
- 이것은 Compute Engine 위에 Google-hosted version의 Kubernetes 가 설치되어 있다
1) Node.js 서버
만들고
- server.js 만들고
- 서버 돌려본다음 종료
2) Docker Container image 만들고
- Dockerfile 만들고 (from 은 Cloud 의
docker hub 에서 가져온다?)
- 빌드하고 런하고 종료한다
- 이미지를 registry 에 push
3) Container cluster 만들고
- 웹콘솔에서 만들어봄
4) Kubernetes pod를 만들고
5) 나의 서비스를 scale up!
Google Cloud Shell 에서 server.js 파일을 다음과 같이 만들자
var http = require('http'); var handleRequest = function(request, response) { response.writeHead(200); response.end("Hello World!"); } var www = http.createServer(handleRequest); |
|
그리고 서버를
실행시키자
- preview on port 8080 을 선택하면 볼 수 있다.
node server.js |
|
Cloud Shell 에서 Ctrl-c 를 눌러서 서버 중지
1) Dockerfile 은
우리가 만들 Docker image 의 설계도랄 수 있겠다.
- 나중에 이렇게 만들어줘! 하고 주면 되는거다.
2) Docker Container Image는 기존의 image 에서 확장이 가능하다.
- node image를
가져와서
- 그 위에 우리의 server.js 만 덧붙여 올릴거다.
Dockerfile 을 아래와 같이 만들자
|
1. 기존에 GCP의
Docker hub 에 있는 node:6.9.2 라는 도커이미지를 2. 8080 포트를 expose 한
상태에서 3. server.js 를 복사해 붙이겠다. 점(.)은 현재 디렉토리를 의미하는 것 같다. 4. 그리고 node.js 서버를
동작시키는 명령을 실행하라 - node server.js |
- PROJECT_ID 에는
진짜 내 프로젝트 아이디를 넣어야겠지?
- 도커이미지의 이름은
hello-node:v1 버전 1이라는 의미구만
- gcr.io 도 중요하다.
- Google Container Registry 라는 도커 이미지를 넣어두는 공간
- Google Cloud Storage 에서 gs:// 라고
prefix 해주던 것과 유사한듯
질문! 여기서 gcr.io로 시작하는 것은 무얼 의미하는가? us.gcr.io 라면 Registry 위치가 미국, 없으면 디폴트로 미국인듯 유럽이나
아시아로 선택할 수도 있나보다 Registry 라면 나중에 push를 또하는건 뭐지? PROJECT_ID 부분은
옵션으로 보인다. 아무 이름이나 가능한듯 아무래도
프로젝트 아이디를 넣으면 낸중에 알아보기 편할듯 마지막으로 -t 는 tag,
점(.)은 Dockerfile의 위치를 의미한다
|
docker build -t gcr.io/PROJECT_ID/hello-node:v1 .ㄷ |
|
빌드되면 난수들이
나올 것이다. 그러면 완성
- Dockerfile 내용이
순서대로 실행되는게 보인다
- 중간 임시 파일들이
생성되고 삭제된다
이제는 run
-d, --detach=false 라고 하여 Detached, daemon 모드라고 하며 컨테이너가 백그라운드로 실행됨
-p, --pubilsh=[] 라고 하여 <호스트포트>:<컨테이너포트> 를 의미한다
이 자체로
도커 이미지가 Running !
결과를 보는
세 가지 방법
1) Shell 의 Preview on port 8080 선택
2) curl 또는 wget 사용
- culr http://localhost:8080
- 결과는
1) 그냥 날로 node.js 서버를 실행시키거나
2) 도커 이미지로 실행시키는
방법을 배웠다.
1) PROJECT_ID를
안쓰고 그냥 아무 이름이나 써봤다
- 만들어지긴
하는데 나중에 push 할때 안된다.
- 아마도 프로젝트 하위로 container registry 가 있기에 그런가보다
2) ./docker_test 라는 폴더를 만들고 거기에 Dockerfile을 만든다음에 node:8.7.0 을 베이스로 이미지를 만들어봤다.
- ./docker_test 폴더로 server.js 파일 복사했고
- 빌드시에 폴더를 명시했다
실습수 docker images --all 로 이미지들을 살펴보았다
|
docker ps 라고 치면 컨테이너 정보들이 나온다 |
|
- docker stop <CONTAINER
ID> 를 치면 멈춘다 - 리턴값은 컨테이너 아이디이다 |
Google Container Registry https://cloud.google.com/container-registry/
- 도커 이미지를 저장해두는
개인 공간이다.
- 따라서 개인의 Project 에서 접근이 가능하다
집어넣기
몇 분 걸리며
아래와 같이 나온다
The push refers to a repository [gcr.io/qwiklabs-gcp-6h281a111f098/hello-node] ba6ca48af64e: Pushed 381c97ba7dc3: Pushed 604c78617f34: Pushed fa18e5ffd316: Pushed 0a5e2b2ddeaa: Pushed 53c779688d06: Pushed 60a0858edcd5: Pushed b6ca02dfe5e6: Pushed v1: digest: sha256:8a9349a355c8e06a48a1e8906652b9259bba6d594097f115060acca8e3e941a2 size: 2002 |
|
웹콘솔의 Tools >> Container Registry 에서 볼 수 있다.
- 퀵랩실습과 내계정으로
한 실습이 섞여 캡처했으니 프로젝트명 바뀌는건 양해를
이제 프로젝트
어디에서나 접근이 가능한 도커 이미지가 준비되었다.
= Kubernetes 가
접근해서 오케스트레이션 가능하다!
현재까지
- node.js 서버하나
만들어서 돌려봤고
- Dockerfile을
만들어 도커 이미지를 build한다음에 Google Container
Registry에 집어넣었다.
Container Engine cluster 를 만들자
- Cluster = Kubernetes master API + worker nodes
- Kubernetes master API는 구글이 hosting 해준다
- worker nodes = Compute Engine VM 이다.
웹콘솔에서
만들수도 있고, Google Cloud Shell 에서 만들수도 있다.
Container Engine > Container Clusters > Create a container
cluster.
1) 프로젝트 설정 제대로
했나 확인
gcloud config set project PROJECT_ID
2) 클러스터 생성
|
1) hello-world 라는 클러스터를 만들라 2) 노드는 두 개다. = VM 두개
만든다? 3) VM의 타입은
n1-standard-1 이고 4) zone 은 us-central1-f
이다 |
웹콘솔의 Container Engine에 가보면 생성된 것을 확인할 수 있다
1) 내 프로그램 server.js 를 container image 로 만들어서 container registry 에 넣어두었다.
- 아래 빨간색
2) Kubernetes cluster를 만들었다.
- 아래 파란색
이제 kubectl 이라는 CLI 로 이미지를 클러스터에 올려보자
- container 들을
하나의 그룹으로 묶은 것이다.
- Administration = 관리 하려고
- Networking = 내부에서
서로 통신하려고
|
- hello-node 라는 이름으로 deploy 하라 - 사용할 이미지는 container Registry 의 hello-node:v1 이고 - 포트는 8080 이다 * 여기서 hello-node 라는 이름은 좀 헷갈린다. hello-node-deployment 는 어떨까? * 궁금증. Kubernetes cluster 인 hello-world 는
언급 안했는데 괜찮나? 자동으로 알아서 현재 클러스터를 안다?
그렇다면 클러스터 여러 개라면? |
궁금증
때문에 두개의 cluster를 만들어보았다
- 두 개중에
두번째 클러스터랑 붙더라
웹콘솔에서
확인
deployment 는 pod를 만들고 scale 하는 좋은 방법이다
* 참고 node는 하나의 컴퓨터 = VM 이라고 보면된다. 하나의 컴퓨터 = VM 안에 여러 개의 컨테이너가 돌 수 있다.
|
deploy 한 것들 보는 방법 deploy 가 pod의 상위개념! |
|
pod 들을 보는 방법 |
|
관련 정보 보는 명령 |
|
tourbleshooting 명령 |
pod를 만들었는데 이건
아직 internal IP로만 접근할 수 있다. =
Kubernetes virtual network
이걸 바깥에서
접근하려면 Kubernetes service 로 pod를 expose 해줘야 한다
주의
1) 우리는 deployment 를 expose 했지 pod을 바로 expose 한 것이 아니다
2) 무얼 의미하냐면 deployment 가 pod 들로가는 traffic 을 챙긴다는 것이다
- 현재야 pod가 하나뿐이긴 하다만, 이후 몇 개의 복제 pod를 더 추가할거다
|
1) kubectl get services 명령으로 볼 수 있다 2) 위에거만 외부에 노출된 것을 알 수 있다 - AGE를 보면 위에거는
방금 명령으로 생겨난 것이라 1m 밖에 안된다. * The EXTERNAL-IP may take several minutes to
become available and visible. If the EXTERNAL-IP is missing,
wait a few minutes and try again. |
현재까지 정리
- 우리 앱을 컨테이너에
집어넣고, 쿠베르네티스로 관리하는 거 까지 봤다.
- 또 뭘 할 수 있을까?
초록색 kubectl 명령으로
- run 명령으로 registry의 이미지를 불러와서 Cluster에 집어넣었고
- expose 명령으로 EXTERNAL-IP를 생성했다. 이때 deployment를 만들때 명시한 8080포트를 이용해야만 볼 수
있다는 것 잊지말자
|
app을 스케일 업 하고 싶다면? 이렇게만 명령주면 4개로 복제된다 |
|
deployments 정보 |
|
1개 이던게 총 4개의 pod 가 되어버림 |
- 클러스터 생성시에 2개의 노드(=VM)를 가지겠다고 했고
- 그런 클러스터를 테스트삼아
두개 만든거다
- Scale 전후의 노드
개수는 변동이 없다.
- 노드(=VM) 안에 여러 개의 Pods (= 컨테이너라고 할까?)가 들어갈 수 있기 때문이다.
- 두 번째 만든 클러스터에 deploy 되었구나
|
1) Cloud Shell 에서 kubectl 로 Kubernetes Cluster로 명령 보낼 수 있다. 2) 다양한 device에서 External IP를 통해서 연결이 들어온다 - 123.45.678.9:8080 - Hello Service 에서 노드들에 나눠준다 궁금증 - node #1, node #2 와 그 안의 Hello Node Pod 간의 상관관계는 ? - 노드는 진짜 하나의
컴퓨터 개념 = VM 이라면 - Pods는 하나의
컴터안에서 도는 컨테이너 개수라고 할까? - Replication controller 는? |
여기까지 우리의 service.js 를 서비스하게 되었다.
그런데 service.js 를 bugfix하고, feature를 추가하고, refactoring 한다면?
- 업그레이드 하는 방법을
알아보자
1. 일단 앱을 수정한다
2. 수정한 앱으로 새로운 container image를 만들고, registry에 밀어넣는다 (v2로 버전업 명시)
|
1) . 은 현재폴더. 현재폴더에
있는 Dockerfile에 기반하여 이미지를 만들라는 것 2) 만든 이미지를
registry에 push |
replication controller 만 수정하면 된다
kube edit 명령만 치면 된다
# Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: extensions/v1beta1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: 2016-03-24T17:55:28Z generation: 3 labels: run: hello-node name: hello-node namespace: default resourceVersion: "151017" selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/hello-node uid: 981fe302-f1e9-11e5-9a78-42010af00005 spec: replicas: 4 selector: matchLabels: run: hello-node strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 type: RollingUpdate template: metadata: creationTimestamp: null labels: run: hello-node spec: containers: - image: gcr.io/PROJECT_ID/hello-node:v1 ## Update this line ## imagePullPolicy: IfNotPresent name: hello-node ports: - containerPort: 8080 protocol: TCP resources: {} terminationMessagePath: /dev/termination-log dnsPolicy: ClusterFirst restartPolicy: Always securityContext: {} terminationGracePeriodSeconds: 30 |
4. 변경된
것으로 다시 돌리기
get 명령이지만
이걸 해줘야 deployment 가 update 된다.
실제 사용자는
어떤 인터럽트도 느끼지 않고 자연스럽게 버전업을 사용할 수 잇게 된다
Kubernetes cluster dashboard 를 접근하기 위한 설정
- 참고로 여기서 hello-world 는 클러스터 이름임
그리고 8081로 접근하면 된다
- 음… 그런데 해보는데
안된다.
- https://github.com/kubernetes/kubernetes/issues/52729
1) 일단 프록시 포트
설정
2) 내 컴퓨터의 브라우저를
열고 127.0.0.1:8081 을 열면
아래와 같이 나온ㄷ
3) 원래는 여기에 ui 만 붙인 https://goo.gl/dT99Hm
만 치면
http://127.0.0.1:8081/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy
로
redirection 되면서 되어야 한다.
그런데 이 url 은 틀렸다. 정답은 아래!
- 맨 끝에 /를 넣어주거나 http://127.0.0.1:8081/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy/ - proxy 단어 위치를
namepaces 앞으로 옮기고 맨 끝에 /를 넣어주면 된다. http://127.0.0.1:8081/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/ |
노드의 key/value 쌍인 labels 참고
- service의 LoadBalancer는 이 라벨로 노드들에 명령을 보낼 수 있다.
- 같은 라벨의 노드가 3개라면? 3개에 동시에 보내는 거다
- 또 다른 라벨로 명령을
보내느데 그건 또 다른 쌍으로 5개의 노드를 가리킨다면? 그 5개에만 보내는거다
Microsoft OneNote 2016에서 작성